package logger

import (
	"fmt"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"io"
	"os"
	"strings"
	"time"
)

type Log struct {
	*zap.Logger                    // 接收任意类型
	Sugared     *zap.SugaredLogger // 接收强类型 必须是zap中的类型 性能up
	LogType     string             // 日志名 gateway worker
}

var WorkerLog *Log
var GatewayLog *Log
var TimerLog *Log
var EasyLog *Log
var ModelLogLog *Log

func init() {
	EasyLog = NewEasyLog()

	// debug模式下默认EasyLog
	WorkerLog = EasyLog
	GatewayLog = EasyLog
	TimerLog = EasyLog
	ModelLogLog = EasyLog
}

// InitLog 初始化log
// 通过main.py一键启动，相同类型的多个服务实例会导致log覆盖
// 正确的做法应该是单独取启动每个服务实例 或者 通过main.py一键启动的服务实例不同类型只有一个
func InitLog(key, logType string) {
	logType = strings.Replace(logType, ":", "-", -1)
	switch key {
	case "worker":
		WorkerLog = NewLog(logType)
	case "gateway":
		GatewayLog = NewLog(logType)
	case "timer":
		TimerLog = NewLog(logType)
	case "modellog":
		ModelLogLog = NewLog(logType)

	}
}

func NewEasyLog() *Log {
	// 创建具体的Logger
	core := zapcore.NewTee(
		zapcore.NewCore(getEncoder(false, true), zapcore.AddSync(os.Stdout), zapcore.DebugLevel), // 输出到控制台
	)
	log := zap.New(core)

	return &Log{
		Logger: log,
	}

}

func NewLog(logType string) *Log {
	// 创建具体的Logger
	core := zapcore.NewTee(
		zapcore.NewCore(getEncoder(true, true), zapcore.AddSync(os.Stdout), zapcore.DebugLevel),            // 输出到控制台
		zapcore.NewCore(getEncoder(true, false), zapcore.AddSync(getFileHook(logType)), zapcore.WarnLevel), // 输出到文件
	)
	log := zap.New(
		core,
		zap.AddCaller(), // 显示文件名和行数
	)
	// 接收强类型 必须是zap中的类型
	sugaredLog := log.Sugar()

	return &Log{
		Logger:  log,
		Sugared: sugaredLog,
		LogType: logType,
	}

}

// 日志配置
func getEncoder(caller bool, errorColor bool) zapcore.Encoder {
	encoderConfig := zap.NewProductionEncoderConfig()
	// 自定义日志时间格式
	encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString("【" + t.Format("2006/01/02 15:04:05.000") + "】")
	}
	// 自定义日志时间格式
	encoderConfig.EncodeLevel = func(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString("【" + level.CapitalString() + "】")
	}
	// 自定义文件行号格式
	encoderConfig.EncodeCaller = func(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString("【" + caller.TrimmedPath() + "】")
	}
	// 自定义换行符
	encoderConfig.LineEnding = "\n\n"

	// 追踪文件位置
	if !caller {
		encoderConfig.EncodeCaller = nil
	}
	// level大写染色编码器
	if errorColor {
		encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
	}

	encoder := zapcore.NewConsoleEncoder(encoderConfig)

	return encoder
}

// 文件写入hook
func getFileHook(logType string) io.Writer {
	_filePath := GetFilePath("log/" + logType + "/%Y-%m-%d-%H.log")
	hook, err := rotatelogs.New(
		_filePath, // log文件目录
		rotatelogs.WithMaxAge(time.Hour*24*7),  // 文件最多保留7天
		rotatelogs.WithRotationTime(time.Hour), // 每1小时分割一次日志
	)

	if err != nil {
		panic(err)
	}
	return hook
}

func Date() string {
	return time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05")
}

// Print 打印
func Print(msg any, fmtMsg ...any) {
	// 需要格式化
	if len(fmtMsg) > 0 {
		_, ok := msg.(string)
		if ok && strings.Contains(msg.(string), "%") {
			msg = fmt.Sprintf(msg.(string), fmtMsg...)
		}
	}
	fmt.Printf("【%s】 %v\n", Date(), msg)
}
